#pragma once

#include <string>
#include <vector>
#include <map>
#include <optional>
#include <nlohmann/json.hpp>
#include "base_noncopyable.h"
namespace El {
namespace Cloud {

class CloudModelImage {
    DISALLOW_COPY_AND_MOVE(CloudModelImage);

public:
    struct ImageData {
        const uint8_t *data;
        size_t size;
        int32_t width;
        int32_t height;
    };

    static CloudModelImage &GetInstance();

    void Start();

    void Stop();

    int32_t NewConversation();

    bool DeleteConversation(int32_t conversation_id);

    std::string AnalyzeImage(int32_t conversation_id, const ImageData &image_data, const std::string &prompt);

    std::string GenerateText(int32_t conversation_id, const std::string &prompt);

private:
    CloudModelImage();
    ~CloudModelImage() = default;

    bool InitConfig();
    static size_t WriteCallback(void *contents, size_t size, size_t nmemb, std::string *s);
    std::string SendHttpRequest(const std::string &post_data, const std::string &url);
    std::string ParseResponse(const std::string &response);
    std::string ParseTextGenerationResponse(const std::string &response);
    std::string ProcessMessage(int32_t conversation_id,
                               const nlohmann::json &message,
                               const std::optional<ImageData> &img_data);
    size_t CalculateImageTokens(int width, int height);
    size_t CalculateTextTokens(const std::string &text);
    size_t CalculateMessageTokens(const nlohmann::json &message, const std::optional<ImageData> &img_data);

private:
    std::string api_key_;
    std::string api_url_;
    std::map<int32_t, std::vector<std::pair<nlohmann::json, std::optional<ImageData>>>> conversations_;
    std::string model_;
    size_t max_context_length_{0};
    int32_t next_conversation_id_{0};
};

} // namespace Cloud
} // namespace El
